﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using IISFileManager.Common;
using System.Security.Permissions;
using ICSharpCode.SharpZipLib.Zip;

namespace IISFileManager.Controllers
{
    public class FileController : Controller
    {

		#region protected override void  OnException(ExceptionContext filterContext)
		protected override void OnException(ExceptionContext filterContext)
		{
			Utils.Log(filterContext.Exception.ToString());
			base.OnException(filterContext);
		}
		#endregion


        public DirectoryInfo Folder;

        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
            base.Initialize(requestContext);

            Folder = new DirectoryInfo(Path.GetTempPath() + "NSUploader\\" + Request.Url.Host );
            if (!Folder.Exists)
                Folder.Create();
        }

        //
        // GET: /File/

        public ActionResult Index()
        {
            return View();
        }

		public ActionResult Test() {
			return Content("Installation Successful.");
		}

        [HttpPost]
        [Authorize]
        public ActionResult NewSession() {

			//Utils.LogAll();

            string sid = DateTime.Now.Ticks.ToString();
            Folder.CreateSubdirectory(sid);
            return Content(sid);
        }

        [HttpPost]
        [Authorize]
        public ActionResult Upload(string sid,int index)
        {
            DirectoryInfo dir = new DirectoryInfo( Folder.FullName + "\\" + sid);
            var f = Request.Files[0];
            f.SaveAs(dir.FullName + "\\" + index.ToString() + ".dat");
            return Content("Success");
        }

        [HttpPost]
        [Authorize]
        public ActionResult Deploy(string sid, string indexList) {
            DirectoryInfo dir = new DirectoryInfo(Folder.FullName + "\\" + sid);
            string zipPath = dir.FullName + "\\Zip.zip";
            using (FileStream fs = System.IO.File.OpenWrite(zipPath))
            {
                foreach (var item in indexList.Split(','))
                {
                    string path = dir.FullName + "\\" + item + ".dat";
                    byte[] all = System.IO.File.ReadAllBytes(path);
                    fs.Write(all,0,all.Length);
                }
            }

            // now deploy on IIS...
            using(FileStream fs = System.IO.File.OpenRead(zipPath)){
                using (ZipFile file = new ZipFile(fs)) {
					DeployInIIS(path=>{
						ExtractFiles(file, path);
					});
                    
                }
            }

            Folder.Delete(true);
            
            return Content("Success");
        }

		#region private void ExtractFiles(ZipFile file,string path)
		private void ExtractFiles(ZipFile zipFile, string path)
		{
			string log = "Extracted\r\n";
			foreach (ZipEntry item in zipFile)
			{
				string fullName;
				if (item.Name.StartsWith("\\"))
				{
					fullName = path + item.Name;
				}
				else {
					fullName = path + "\\" + item.Name;
				}

				log += fullName + "\r\n";

				FileIOPermission writeAccess = new FileIOPermission(FileIOPermissionAccess.AllAccess, fullName);
				writeAccess.Demand();

				FileInfo file = new FileInfo(fullName);
				if (file.Exists)
					file.Delete();

				if (!file.Directory.Exists)
					file.Directory.Create();

				using (FileStream fs = file.OpenWrite()) {
					using (Stream s = zipFile.GetInputStream(item))
					{
						s.CopyTo(fs);
					}
				}
			}

			log += " at " + path;
			Utils.Log(log);
		}
		#endregion


        #region GetIISRootFolder
        private void DeployInIIS(Action<string> pathAction)
        {
            string websiteBinding = Request.Url.Host;

            #region IIS 6.0
            //DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");
            //websiteBinding = websiteBinding.ToLower();

            //foreach (DirectoryEntry server in root.Children)
            //{
            //    if (server.SchemaClassName == "IIsWebServer")
            //    {
            //        object val = server.Properties["ServerBindings"].Value;
            //        List<string> bindings = new List<string>();
            //        if (val is Array)
            //        {
            //            foreach (object b in (Array)val)
            //            {
            //                bindings.Add(b.ToString());
            //            }
            //        }
            //        else
            //        {
            //            if (val != null)
            //            {
            //                bindings.Add(val.ToString());
            //            }
            //            else
            //            {
            //                bindings.Add("null");
            //            }
            //        }
            //        foreach (string binding in bindings)
            //        {
            //            foreach (DirectoryEntry dir in server.Children)
            //            {
            //                if (dir.SchemaClassName == "IIsWebVirtualDir")
            //                {
            //                    string b = binding.ToLower();
            //                    if (b.Contains(websiteBinding))
            //                    {
            //                        return (string)dir.Properties["Path"].Value;
            //                    }
            //                }
            //            }
            //        }
            //    }
            //}
            //throw new InvalidOperationException("No server bindings found");
            #endregion

            Microsoft.Web.Administration.ServerManager sm = new Microsoft.Web.Administration.ServerManager();
            var site = sm.Sites.FirstOrDefault(y => y.Bindings.Any(x => x.Host != null && string.Compare(x.Host, websiteBinding, true) == 0));

            string path = null;

            if (site != null)
            {
                var app = site.Applications.FirstOrDefault();
                if (app != null)
                {
                    var v = app.VirtualDirectories.FirstOrDefault();
                    if (v != null)
                    {
                        path = v.PhysicalPath;
                    }
                }
            }
            if(String.IsNullOrWhiteSpace(path))
            throw new ArgumentException("No binding found for " + websiteBinding);

            site.Stop();

            pathAction(path);

            site.Start();

        }
        #endregion
    }
}
